using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Splino.D3D
{
    /// <summary>
    /// A form with a sortable list of every Splino Object in the scene
    /// along with the object's properties
    /// </summary>
    public partial class SceneManagerTree : Form
    {
        /// <summary>
        /// Gets the ListView that displays all objects in the scene
        /// </summary>
        public ListView ListView
        {
            get { return _listView.ListView; }
        }

        SplinoObject _lastSelectedNodeObject = SceneManager.Instance.MasterSceneObject;

        /// <summary>
        /// Constructor
        /// </summary>
        public SceneManagerTree()
        {
            InitializeComponent();

            foreach (SplinoObject sceneObject in 
                SceneManager.Instance.MasterSceneObject.SceneChildren)
            {
                _listView.AddListViewItem(sceneObject, true);
            }

            FillTreeView(SceneManager.Instance.MasterSceneObject);

            _treeView.Nodes[0].ImageIndex = 1000;
            _treeView.Nodes[0].SelectedImageIndex = 1000;
            _treeView.Nodes[0].Expand();
            _treeView.Nodes[0].Tag = SceneManager.Instance.MasterSceneObject;

            SceneManager.Instance.SplinoObjectInitialized +=
                new SplinoObjectInitializedEventHandler(Instance_SplinoObjectInitialized);

            SceneManager.Instance.SplinoObjectLocked +=
                new SplinoObjectLockedEventHandler(Instance_SplinoObjectLocked);

            SceneManager.Instance.SplinoObjectUnlocked +=
                new SplinoObjectUnlockedEventHandler(Instance_SplinoObjectUnlocked);

            SceneManager.Instance.SplinoObjectHidden +=
                new SplinoObjectHiddenEventHandler(Instance_SplinoObjectHidden);

            SceneManager.Instance.SplinoObjectShown +=
                new SplinoObjectShownEventHandler(Instance_SplinoObjectShown);

            SceneManager.Instance.SplinoObjectColorChange +=
                new SplinoObjectColorChangeEventHandler(Instance_SplinoObjectColorChange);

            SceneManager.Instance.SplinoObjectSelected += 
                new SplinoObjectSelectedEventHandler(Instance_SplinoObjectSelected);

            SceneManager.Instance.SplinoObjectDeselected +=
                new SplinoObjectDeselectedEventHandler(Instance_SplinoObjectDeselected);
        }

        /// <summary>
        /// Recrusively fills the TreeView with nodes representing each Splino Object in the scene
        /// </summary>
        /// <param name="parentObject">The parent scene object</param>
        private void FillTreeView(SplinoObject parentObject)
        {
            foreach (SplinoObject childObject in parentObject.SceneChildren)
            {
                AddTreeNode(childObject);
                FillTreeView(childObject);
            }
        }

        private void Instance_SplinoObjectInitialized(object sender, SplinoObjectEventArgs e)
        {
            AddTreeNode(e.SplinoObject);

            if (e.SplinoObject.SceneParent == _lastSelectedNodeObject)
                _listView.AddListViewItem(e.SplinoObject, true);

            _treeView.SelectedNode = null;
        }

        private void Instance_SplinoObjectLocked(object sender, SplinoObjectEventArgs e)
        {
            ListViewItem listViewItem = _listView.FindSplinoObjectsListViewItem(e.SplinoObject);
            if (listViewItem != null)
            {
                ListViewImageSubItem imageSubItem = (ListViewImageSubItem)listViewItem.SubItems[3];
                imageSubItem.Checked = true;
            }
        }

        private void Instance_SplinoObjectUnlocked(object sender, SplinoObjectEventArgs e)
        {
            ListViewItem listViewItem = _listView.FindSplinoObjectsListViewItem(e.SplinoObject);
            if (listViewItem != null)
            {
                ListViewImageSubItem imageSubItem = (ListViewImageSubItem)listViewItem.SubItems[3];
                imageSubItem.Checked = false;
            }
        }

        private void Instance_SplinoObjectHidden(object sender, SplinoObjectEventArgs e)
        {
            ListViewItem listViewItem = _listView.FindSplinoObjectsListViewItem(e.SplinoObject);
            if (listViewItem != null)
            {
                ListViewImageSubItem imageSubItem = (ListViewImageSubItem)listViewItem.SubItems[4];
                imageSubItem.Checked = false;
            }
        }


        private void Instance_SplinoObjectShown(object sender, SplinoObjectEventArgs e)
        {
            ListViewItem listViewItem = _listView.FindSplinoObjectsListViewItem(e.SplinoObject);
            if (listViewItem != null)
            {
                ListViewImageSubItem imageSubItem = (ListViewImageSubItem)listViewItem.SubItems[4];
                imageSubItem.Checked = true;
            }
        }

        private void Instance_SplinoObjectColorChange(object sender, SplinoObjectEventArgs e)
        {
            ListViewItem listViewItem = _listView.FindSplinoObjectsListViewItem(e.SplinoObject);
            if (listViewItem != null)
            {
                listViewItem.SubItems[2].BackColor = e.SplinoObject.Color;
            }
        }

        private void Instance_SplinoObjectSelected(object sender, SplinoObjectEventArgs e)
        {
            ListViewItem listViewItem = _listView.FindSplinoObjectsListViewItem(e.SplinoObject);
            if (listViewItem != null)
            {
                listViewItem.Selected = true;
            }
        }

        private void Instance_SplinoObjectDeselected(object sender, SplinoObjectEventArgs e)
        {
            ListViewItem listViewItem = _listView.FindSplinoObjectsListViewItem(e.SplinoObject);
            if (listViewItem != null)
            {
                listViewItem.Selected = false;
            }
        }

        private void AddTreeNode(SplinoObject splinoObject)
        {
            if (splinoObject.SceneParent == SceneManager.Instance.MasterSceneObject)
            {
                TreeNode treeNode = _treeView.Nodes[0].Nodes.Add(
                    splinoObject.Name,
                    splinoObject.Name,
                    splinoObject.TreeNodeImageKey,
                    splinoObject.TreeNodeImageKey);
                treeNode.Tag = splinoObject;

                if (!_treeView.Nodes[0].IsExpanded)
                    _treeView.Nodes[0].Expand();
            }
            else
            {
                TreeNode[] treeNodes = _treeView.Nodes.Find(splinoObject.SceneParent.Name, true);
                TreeNode treeNode = treeNodes[0].Nodes.Add(
                    splinoObject.Name,
                    splinoObject.Name,
                    splinoObject.TreeNodeImageKey,
                    splinoObject.TreeNodeImageKey);
                treeNode.Tag = splinoObject;
            }
        }

        private void SceneManagerTree_FormClosed(object sender, FormClosedEventArgs e)
        {
            SceneManager.Instance.MasterSceneObject.PropertiesWindowActive = false;
        }

        private void _listView_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            SplinoObject splinoObject = (SplinoObject)_listView.Items[e.Item].Tag;
            if (!SceneManager.Instance.CheckForDuplicateName(e.Label))
            {
                _listView.Items[e.Item].Name = e.Label;
                splinoObject.Name = e.Label;
            }
            else
            {
                MessageBox.Show("Cannot rename " +
                    _listView.Items[e.Item].Name +
                    ": An object with the name " + e.Label +
                    " already exists.", "Error Renaming Object",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                e.CancelEdit = true;
            }
        }

        private void _listView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            SplinoObject splinoObject = (SplinoObject)e.Item.Tag;

            if (e.IsSelected)
                splinoObject.Select();
            else
                splinoObject.Deselect();
        }

        private void cutToolStripButton_Click(object sender, EventArgs e)
        {
            CommandManager.Instance.ExecuteCommand(new Commands.CutClipboard());
        }

        private void copyToolStripButton_Click(object sender, EventArgs e)
        {
            CommandManager.Instance.ExecuteCommand(new Commands.CopyClipboard());
        }

        private void pasteToolStripButton_Click(object sender, EventArgs e)
        {
            CommandManager.Instance.ExecuteCommand(new Commands.PasteClipboard());
        }

        private void SceneManagerTree_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Escape:
                    Close();
                    break;
                case Keys.Delete:
                    CommandManager.Instance.ExecuteCommand(new Commands.Delete());
                    break;
            }
        }

        private void _listView_KeyUp(object sender, KeyEventArgs e)
        {
            SceneManagerTree_KeyUp(sender, e);
        }

        private void _sceneManagerToolStrip_KeyUp(object sender, KeyEventArgs e)
        {
            SceneManagerTree_KeyUp(sender, e);
        }

        private void _treeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            SceneManager.Instance.ClearSelectedItems();
            SplinoObject splinoObject = (SplinoObject)e.Node.Tag;
            if (splinoObject != null && splinoObject.Type != SplinoObjectType.System)
            {
                CommandManager.Instance.ExecuteCommand(
                    new Commands.Select_System(new SplinoObject[] { splinoObject }));
            }
            _listView.Items.Clear();

            if (splinoObject.Type != SplinoObjectType.System)
                _listView.AddListViewItem(splinoObject, false);

            foreach (SplinoObject childObject in splinoObject.SceneChildren)
                _listView.AddListViewItem(childObject, true);

            if (_listView.Items.Count > 0)
                _listView.Items[0].Selected = true;
        }

    }
}